/**
 * 初识接口
 */
function printLabel(labeledObj:{label:string}){
  console.log(labeledObj.label);
}
let myObj = {size:10, label:"Size 10 Object"};
printLabel(myObj);

// 重写后
interface LabeledValue{
  label:string;
}
function printLabelTo1(labeledObj:LabeledValue){
  console.log(labeledObj.label);
}
let myObjTo1 = {size:10, label:"Size 10 Object"};
printLabelTo1(myObjTo1);

/**
 * 可选属性 —— ?
 */
interface SquareConfig{
  color?:string;  
  width?:number;
}
function createSquare(config:SquareConfig):{color:string,area:number} {
  const newSquare = {color:"white",area:100}
  if(config.color){
    newSquare.color = config.color
  }
  if(config.width){
    newSquare.area = config.width * config.width;
  }

  return newSquare
}

/**
 * 只读属性 —— readonly
 */
interface Point{
  readonly x:number; 
  readonly y:number;
}

let p1:Point = {x:10,y:20};
// p1.x = 3  //无法为“x”赋值，因为它是只读属性。
//只读泛型 ReadonlyArray<T>
let a:number[] = [1,2,3,4];
let ro:ReadonlyArray<number> = a;
// ro[0] =12 //类型“readonly number[]”中的索引签名仅允许读取。
// ro.push(5) //类型“readonly number[]”上不存在属性“push”。
// ro.length =10  //无法为“length”赋值，因为它是只读属性。
// a = ro  //类型 "readonly number[]" 为 "readonly"，不能分配给可变类型 "number[]"

//使用类型断言重写
a = ro as number[]

/**
 * 函数类型
 */
interface SearchFunc {
  (source:string,subString:string) :boolean;
}
let mySearch:SearchFunc;
mySearch = function(sour:string,subStr:string){
  let result = sour.search(subStr);
  return true || result > -1   //函数的返回值类型是通过其返回值推断出来的
}
let mySearchTo1:SearchFunc;
mySearchTo1 = function(src,sub){ //TypeScript 的类型系统会推断出参数类型
  let result = src.search(sub);
  return result > -1
}

/**
 * 可索引的类型
 */
interface StringArray {
  [index:number]:string;
}
let myArray:StringArray;
myArray = ["Bob","Fred"];
let myStr:string = myArray[0]
// 对象中
interface StringObject {
  [x:string]:string
}
let ad:StringObject = {
  city:"cds",
}
// 联合类型
interface NumberOrStringDictionary{
  [index:string]:number | string;
  length:number;
  name:string;
}
// 索引只读
interface ReadonlyStringArray {
  readonly [index:number]:string;
}
let myArrayTo1:ReadonlyStringArray = [ "Alice","Bob"]
// myArrayTo1[0] = "Ad" //类型“ReadonlyStringArray”中的索引签名仅允许读取。

/**
 * 类类型 ——实现接口
 */
interface ClockInterface {
  currentTim:Date;
}
class Clock implements ClockInterface { 
  currentTim: Date = new Date();
  constructor (h:number,m:number) {};
}
// 在接口中描述一个方法，在类里实现
interface ClockInter {
  currentTime:Date;
  setTime(d:Date):void;
}
class ClockTo1 implements ClockInter {
  currentTime:Date = new Date()
  setTime(d:Date) {
    this.currentTime = d;
  }
  constructor(h:number,m:number){}
}
/**
 * 继承接口 ——接口继承接口
 */
interface Shape {
  color: string;
}
interface PenStroke {
  penWidth: number;
}
interface Square extends Shape, PenStroke {
  sideLength: number;
}
let square = {} as Square;
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;

/**
 * 混合类型 ???????
 */

/**
 * 接口继承类 ??????
 */